package com.atguigu.tingshu.album.service.impl;

import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackStatMapper;
import com.atguigu.tingshu.album.service.TrackInfoService;
import com.atguigu.tingshu.album.service.VodService;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.common.result.ResultCodeEnum;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.album.TrackStat;
import com.atguigu.tingshu.query.album.TrackInfoQuery;
import com.atguigu.tingshu.user.client.UserInfoFeignClient;
import com.atguigu.tingshu.vo.album.*;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"all"})
public class TrackInfoServiceImpl extends ServiceImpl<TrackInfoMapper, TrackInfo> implements TrackInfoService {

    @Autowired
    private TrackInfoMapper trackInfoMapper;

    @Autowired
    private AlbumInfoMapper albumInfoMapper;

    @Autowired
    private TrackStatMapper trackStatMapper;

    @Autowired
    private UserInfoFeignClient userInfoFeignClient;

    @Autowired
    private VodService vodService;

    /**
     * 获取下单声音列表.
     *
     * @param trackId    当前点击的声音Id
     * @param trackCount 购买的集数
     * @return
     */
    @Override
    public List<TrackInfo> findPaidTrackInfoList(Long trackId, Integer trackCount) {
        //  实现：声明一个集合对象
        List<TrackInfo> trackInfoList = new ArrayList<>();

        //  select * from track_info where id = 18031; order_num = 6; album_id = 341;
        TrackInfo trackInfo = this.getById(trackId);
        //  获取已支付的声音Id 列表.
        Result<List<Long>> userPaidTrackList = userInfoFeignClient.findUserPaidTrackList(trackInfo.getAlbumId());
        Assert.notNull(userPaidTrackList, "用户已支付的声音Id结果集为空");
        List<Long> trackIdList = userPaidTrackList.getData();
        Assert.notNull(trackIdList, "用户已支付的声音Id对象为空");

        //  trackCount == 0; 购买的本集; trackCount !=0; 购买很多集；有列表！
        if (trackCount > 0) {
            //  select * from track_info where order_num > 6 and album_id = 341 ;
            LambdaQueryWrapper<TrackInfo> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(TrackInfo::getAlbumId, trackInfo.getAlbumId());
            wrapper.gt(TrackInfo::getOrderNum, trackInfo.getOrderNum());
            //  判断用户是否购买过声音
            if (!CollectionUtils.isEmpty(trackIdList)) {
                //  select * from track_info where order_num > 6 and album_id = 341 and id not in(18034,18035);
                wrapper.notIn(TrackInfo::getId, trackIdList);
            }
            //  select * from track_info where order_num > 6 and album_id = 341 and id not in(18034,18035) limit count;
            //  select * from track_info where order_num > 6 and album_id = 341 and id limit count;
            wrapper.last(" limit " + trackCount);
            trackInfoList = trackInfoMapper.selectList(wrapper);
        } else {
            //  trackCount == 0; 购买的本集;
            trackInfoList.add(trackInfo);
        }
        //  返回集合列表。
        return trackInfoList;
    }

    @Override
    public List<Map<String, Object>> findUsertrackIdNoReaptList(Long userId, Long trackId) {
        //  创建对象
        List<Map<String, Object>> list = new ArrayList<>();
        //  根据声音Id 获取到声音对象
        //  select * from track_info where id = 18031; # order_num = 6; album_id = 341;
        TrackInfo trackInfo = this.getById(trackId);
        //  获取当前专辑对象
        AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfo.getAlbumId());
        //  根据当前专辑Id获取到用户已购买的声音Id集合.
        Result<List<Long>> trackIdListResult = userInfoFeignClient.findUserPaidTrackList(trackInfo.getAlbumId());
        Assert.notNull(trackIdListResult, "已购买的声音Id结果集为空");
        List<Long> trackIdList = trackIdListResult.getData();
        Assert.notNull(trackIdList, "已购买的声音Id集合对象为空");

        //  获取当前声音列表{大于当前order_num的数据，必须是同一个专辑.}
        //  select * from track_info where order_num > 6 and album_id = 341;
        LambdaQueryWrapper<TrackInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TrackInfo::getAlbumId, trackInfo.getAlbumId()).gt(TrackInfo::getOrderNum, trackInfo.getOrderNum());
        //  获取到当前所有需要付费声音列表
        List<TrackInfo> trackInfoList = trackInfoMapper.selectList(wrapper);
        //  排查已购买的声音Id,获取最新需要购买的声音Id集合。
        List<TrackInfo> trackIdNoReaptList = trackInfoList.stream().filter(trackInfo1 -> !trackIdList.contains(trackInfo1.getId())).collect(Collectors.toList());

        //  声明变量记录数据
        int totalTrackCount = trackIdNoReaptList.size();
        BigDecimal albumPrice = albumInfo.getPrice();
        //  构建分集购买列表.
        //  本集：
        if (totalTrackCount >= 0) {
            //  添加购买本集
            addToPurchaseList(list, "本集", albumPrice, 0);
        }

        //  循环遍历. totalTrackCount = 35
        for (int i = 10; i <= 50; i += 10) {
            if (totalTrackCount > i) {
                //  10的倍数集
                addToPurchaseList(list, "后" + i + "集", albumPrice.multiply(new BigDecimal(i)), i);
            } else {
                //  10的倍数区间集
                addToPurchaseList(list, "后" + totalTrackCount + "集", albumPrice.multiply(new BigDecimal(totalTrackCount)), totalTrackCount);
                break;
            }
        }

        //  后50集：
        if (totalTrackCount > 50) {
            //  添加购买本集
            addToPurchaseList(list, "后50集", albumPrice.multiply(new BigDecimal(50)), 50);
        }

        //        if(trackIdNoReaptList.size() >= 0) {
        //            Map<String, Object> map = new HashMap<>();
        //            map.put("name", "本集");
        //            map.put("price", albumInfo.getPrice());
        //            map.put("trackCount", 0);
        //            list.add(map);
        //        }

        //  后9集
        //        if (trackIdNoReaptList.size() > 0 && trackIdNoReaptList.size() <= 10) {
        //            //  创建Map对象
        //            Map<String, Object> map = new HashMap<>();
        //            //  获取集数
        //            int trackCount = trackIdNoReaptList.size();
        //            map.put("name", "后" + trackCount + "集"); // 显示文本
        //            map.put("price", albumInfo.getPrice().multiply(new BigDecimal(String.valueOf(trackCount)))); // 专辑声音对应的价格
        //            map.put("trackCount", trackCount); // 记录购买集数
        //            list.add(map);
        //        }
        //        //  后10集
        //        if (trackIdNoReaptList.size() > 10) {
        //            //  创建Map对象
        //            Map<String, Object> map = new HashMap<>();
        //            //  获取集数
        //            int trackCount = trackIdNoReaptList.size();
        //            map.put("name", "后10集"); // 显示文本
        //            map.put("price", albumInfo.getPrice().multiply(new BigDecimal(String.valueOf("10")))); // 专辑声音对应的价格
        //            map.put("trackCount", 10); // 记录购买集数
        //            list.add(map);
        //        }
        //
        //        // 后20集
        //        if (trackIdNoReaptList.size() > 10 && trackIdNoReaptList.size() <= 20) {
        //            Map<String, Object> map = new HashMap<>();
        //            int count = trackIdNoReaptList.size();
        //            BigDecimal price = albumInfo.getPrice().multiply(new BigDecimal(count));
        //            map.put("name", "后" + count + "集");
        //            map.put("price", price);
        //            map.put("trackCount", count);
        //            list.add(map);
        //        }
        //        if (trackIdNoReaptList.size() > 20) {
        //            Map<String, Object> map = new HashMap<>();
        //            BigDecimal price = albumInfo.getPrice().multiply(new BigDecimal(20));
        //            map.put("name", "后20集");
        //            map.put("price", price);
        //            map.put("trackCount", 20);
        //            list.add(map);
        //        }
        //
        //        //后30集
        //        if (trackIdNoReaptList.size() > 20 && trackIdNoReaptList.size() <= 30) {
        //            Map<String, Object> map = new HashMap<>();
        //            int count = trackIdNoReaptList.size();
        //            BigDecimal price = albumInfo.getPrice().multiply(new BigDecimal(count));
        //            map.put("name", "后" + count + "集");
        //            map.put("price", price);
        //            map.put("trackCount", count);
        //            list.add(map);
        //        }
        //        if (trackIdNoReaptList.size() > 30) {
        //            Map<String, Object> map = new HashMap<>();
        //            BigDecimal price = albumInfo.getPrice().multiply(new BigDecimal(30));
        //            map.put("name", "后30集");
        //            map.put("price", price);
        //            map.put("trackCount", 30);
        //            list.add(map);
        //        }
        //
        //        //后50集
        //        if (trackIdNoReaptList.size() > 30 && trackIdNoReaptList.size() <= 50) {
        //            Map<String, Object> map = new HashMap<>();
        //            int count = trackIdNoReaptList.size();
        //            BigDecimal price = albumInfo.getPrice().multiply(new BigDecimal(count));
        //            map.put("name", "后" + count + "集");
        //            map.put("price", price);
        //            map.put("trackCount", count);
        //            list.add(map);
        //        }
        //        // 最多购买50集;
        //        if (trackIdNoReaptList.size() > 50) {
        //            Map<String, Object> map = new HashMap<>();
        //            BigDecimal price = albumInfo.getPrice().multiply(new BigDecimal(50));
        //            map.put("name", "后50集");
        //            map.put("price", price);
        //            map.put("trackCount", 50);
        //            list.add(map);
        //        }
        //  返回对象
        return list;
    }

    /**
     * @param list
     * @param name
     * @param price
     * @param count
     */
    private void addToPurchaseList(List<Map<String, Object>> list, String name, BigDecimal price, int count) {
        Map<String, Object> map = new HashMap<>();
        map.put("name", name);
        map.put("price", price);
        map.put("trackCount", count);
        list.add(map);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateTrackStat(TrackStatMqVo trackStatMqVo) {
        //  更新声音播放次数. update track_stat set stat_num = ? where stat_typ=? track_id=?
        trackStatMapper.updateTrackStat(trackStatMqVo.getTrackId(), trackStatMqVo.getStatType(), trackStatMqVo.getCount());
        //  更新一次专辑的播放次数.
        if (SystemConstant.TRACK_STAT_PLAY.equals(trackStatMqVo.getStatType())) {
            //  调用mapper
            albumInfoMapper.updateAlbumStat(trackStatMqVo.getAlbumId(), SystemConstant.ALBUM_STAT_PLAY, trackStatMqVo.getCount());
        }
    }

    @Override
    public IPage<AlbumTrackListVo> findAlbumTrackPage(Long albumId, Page<AlbumTrackListVo> listVoPage, Long userId) {
        //  先根据专辑Id获取到声音列表集合.
        //  select * from track_info where album_id = 1451; 1-25;
        IPage<AlbumTrackListVo> pageInfo = trackInfoMapper.selectAlbumTrackPage(albumId, listVoPage);
        //  根据专辑Id 获取到当前专辑对象.select tracks_for_free from album_info where id = 1451;
        AlbumInfo albumInfo = albumInfoMapper.selectById(albumId);
        //  判断用户Id
        if (null == userId) {
            //  0101-免费 0102-vip付费 0103-付费
            if (!SystemConstant.ALBUM_PAY_TYPE_FREE.equals(albumInfo.getPayType())) {
                //  用户未登录,并且当前专辑属于付费时，除去免费试听集数外，都需要设置为付费标识.
                /*
                select tracks_for_free from album_info where id = 1451;
                select * from track_info where order_num > 5;
                 */
                //  1--25;6-25;
                //  List<AlbumTrackListVo> trackPaidVoList = pageInfo.getRecords().stream().filter(albumTrackListVo -> albumTrackListVo.getOrderNum() > albumInfo.getTracksForFree()).collect(Collectors.toList());
                pageInfo.getRecords().stream().filter(albumTrackListVo -> albumTrackListVo.getOrderNum() > albumInfo.getTracksForFree()).forEach(albumTrackListVo -> {
                    //  修改付费标识
                    albumTrackListVo.setIsShowPaidMark(true);
                });
            }
        } else {
            //  声明一个变量，来存储是否需要付费
            boolean isShowPaidMark = false;
            //  用户不为空.
            if (SystemConstant.ALBUM_PAY_TYPE_VIPFREE.equals(albumInfo.getPayType())) {
                //  vip 免费
                //  获取用户信息.
                Result<UserInfoVo> userInfoVoResult = userInfoFeignClient.getUserInfoVo(userId);
                Assert.notNull(userInfoVoResult, "返回主播结果集为空");
                UserInfoVo userInfoVo = userInfoVoResult.getData();
                Assert.notNull(userInfoVo, "返回主播对象为空");
                //  判断用户的身份.
                if (userInfoVo.getIsVip() == 0) {
                    isShowPaidMark = true;
                }
                //  虽然是vip，但是vip已经过期了.
                if (userInfoVo.getIsVip() == 1 && userInfoVo.getVipExpireTime().before(new Date())) {
                    isShowPaidMark = true;
                }
            } else if (SystemConstant.ALBUM_PAY_TYPE_REQUIRE.equals(albumInfo.getPayType())) {
                //  付费
                isShowPaidMark = true;
            }
            //  处理付费标识：
            if (isShowPaidMark) {
                //  判断当前这个用户是否购买过专辑【user_paid_album】或购买过声音【user_paid_track】.
                //  所有的付费声音列表  6-25集
                List<AlbumTrackListVo> albumTrackNeedPaidListVoList = pageInfo.getRecords().stream().filter(albumTrackListVo -> albumTrackListVo.getOrderNum() > albumInfo.getTracksForFree()).collect(Collectors.toList());
                if (!CollectionUtils.isEmpty(albumTrackNeedPaidListVoList)) {
                    //  将albumTrackNeedPaidListVoList 进行转换 声音Id集合列表.
                    List<Long> trackIdList = albumTrackNeedPaidListVoList.stream().map(AlbumTrackListVo::getTrackId).collect(Collectors.toList());
                    //  需要一个远程调用查询当前用户购买信息记录. key=trackId value = 1或0; 1:表示购买过，0：表示没有购买过
                    //  userId--本地线程获取;albumId;trackIdList key=trackId value = 1或0; 1:表示购买过，0：表示没有购买过
                    Result<Map<Long, Integer>> mapResult = userInfoFeignClient.userIsPaidTrack(albumId, trackIdList);
                    Assert.notNull(mapResult, "用户购买结果集为空");
                    Map<Long, Integer> map = mapResult.getData();
                    Assert.notNull(map, "用户购买对象为空");
                    //  判断要付费的声音Id 列表中，这个用户是否已经购买过.
                    for (AlbumTrackListVo albumTrackListVo : albumTrackNeedPaidListVoList) {
                        //  赋值是否需要付费
                        albumTrackListVo.setIsShowPaidMark(map.get(albumTrackListVo.getTrackId()) == 1 ? false : true);
                    }
                }
            }
        }
        //  返回数据
        return pageInfo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateTrackInfo(Long trackId, TrackInfoVo trackInfoVo) {
        //  判断流媒体Id 是否一致！
        //  先获取到声音对象
        TrackInfo trackInfo = this.getById(trackId);
        //  获取到原有的流媒体Id 1397757888603384004--->1397757888703927900
        String mediaFileId = trackInfo.getMediaFileId();
        //  属性赋值：将修改的数据赋值给tracInfo;
        BeanUtils.copyProperties(trackInfoVo, trackInfo);
        //  用户修改了声音.
        if (!mediaFileId.equals(trackInfoVo.getMediaFileId())) {
            //  说明这个用户修改了声音.
            //  根据最新的流媒体Id 获取 流媒体对象
            TrackMediaInfoVo mediaInfo = vodService.getMediaInfo(trackInfoVo.getMediaFileId());
            if (null == mediaInfo) {
                //  获取数据失败
                throw new GuiguException(ResultCodeEnum.FAIL);
            }
            //  赋值数据.
            trackInfo.setMediaType(mediaInfo.getType());
            trackInfo.setMediaUrl(mediaInfo.getMediaUrl());
            trackInfo.setMediaDuration(mediaInfo.getDuration());
            trackInfo.setMediaSize(mediaInfo.getSize());

            //  删除流媒体：
            this.vodService.removeMediaInfo(mediaFileId);
            //  发布专辑之后，再修改的话，必须要数据同步！
            //  查询购买当前专辑订单用户Id;
            //  发送消息：异步---msg
        }

        this.updateById(trackInfo);

    }

    @Override
    public TrackInfo getTrackInfo(Long trackId) {
        return this.getById(trackId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removeTrackInfo(Long trackId) {
        //  根据声音Id获取到专辑对象
        //  select * from track_info where id = 53;
        TrackInfo trackInfo = this.getById(trackId);
        //  TrackInfo trackInfo1 = trackInfoMapper.selectById(trackId);
        //  track_info track_stat album_info 流媒体;
        trackInfoMapper.deleteById(trackId);

        //  track_stat
        trackStatMapper.delete(new LambdaQueryWrapper<TrackStat>().eq(TrackStat::getTrackId, trackId));

        //  更新专辑包含声音数量.
        AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfo.getAlbumId());
        albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount() - 1);
        //  更新最新数据
        this.albumInfoMapper.updateById(albumInfo);

        //  修改一下当前的order_num;
        //  update track_info set order_num = order_num - 1 where album_id = 1 and order_num > ? and is_deleted = 0;
        trackInfoMapper.updateTrackInfoOrderNum(trackInfo.getAlbumId(), trackInfo.getOrderNum());
        //  删除流媒体数据：
        //  根据trackInfo.getMediaFileId();删除；
        vodService.removeMediaInfo(trackInfo.getMediaFileId());


    }

    @Override
    public IPage<TrackListVo> findUserTrackPage(Page<TrackListVo> trackListVoPage, TrackInfoQuery trackInfoQuery) {
        //  需要多表关联查询.
        return trackInfoMapper.selectUserTrackPage(trackListVoPage, trackInfoQuery);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveTrackInfo(TrackInfoVo trackInfoVo, Long userId) {
        //		track_info
        TrackInfo trackInfo = new TrackInfo();
        //	属性赋值：
        BeanUtils.copyProperties(trackInfoVo, trackInfo);
        //	赋值用户Id
        trackInfo.setUserId(userId);
        //	order_num  声音在专辑中的排序值 获取声音最后一个序号+1;
        LambdaQueryWrapper<TrackInfo> wrapper = new LambdaQueryWrapper<>();
        // select order_num from track_info where album_id = ? order by order_num desc limit 1;
        wrapper.eq(TrackInfo::getAlbumId, trackInfoVo.getAlbumId()).orderByDesc(TrackInfo::getOrderNum).last(" limit 1 ");
        TrackInfo trackInfoCount = trackInfoMapper.selectOne(wrapper);
        //  声明一个变量
        int orderNum = 1;
        if (null != trackInfoCount) {
            orderNum = trackInfoCount.getOrderNum() + 1;
        }
        trackInfo.setOrderNum(orderNum);

        //  根据流媒体Id 获取 声音对象数据
        TrackMediaInfoVo trackMediaInfoVo = vodService.getMediaInfo(trackInfoVo.getMediaFileId());
        trackInfo.setMediaDuration(trackMediaInfoVo.getDuration());
        trackInfo.setMediaUrl(trackMediaInfoVo.getMediaUrl());
        trackInfo.setMediaSize(trackMediaInfoVo.getSize());
        trackInfo.setMediaType(trackMediaInfoVo.getType());
        //  保存声音对象
        trackInfoMapper.insert(trackInfo);
        //		track_stat
        this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_PLAY);
        this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_COLLECT);
        this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_PRAISE);
        this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_COMMENT);
        //		album_info
        AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfoVo.getAlbumId());
        //  修改包含的总声音数量.
        albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount() + 1);
        //  调用修改方法.
        albumInfoMapper.updateById(albumInfo);
    }

    /**
     * 初始化声音统计数据
     *
     * @param trackId
     * @param statPlay
     */
    private void saveTrackStat(Long trackId, String statPlay) {
        TrackStat trackStat = new TrackStat();
        trackStat.setTrackId(trackId);
        trackStat.setStatType(statPlay);
        trackStat.setStatNum(0);
        trackStatMapper.insert(trackStat);
    }
}
